package com.codeoss.framework.view.pagebean;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.converter.IConverter;
import com.codeoss.framework.converter.IConverterStore;
import com.codeoss.framework.data.metadata.Column;
import com.codeoss.framework.data.metadata.Order;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.Restrictions;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.metadata.TableData;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.impexp.ExportManager;
import com.codeoss.framework.util.DataTypeConstants;
import com.codeoss.framework.util.IOUtil;
import com.codeoss.framework.util.StringUtils;
import com.codeoss.framework.util.Utils;
import com.codeoss.framework.view.clientscript.JsWindow;
import com.codeoss.framework.view.clientscript.NavigatePageClientScript;
import com.codeoss.framework.view.component.Component;
import com.codeoss.framework.view.component.IDataBinding;
import com.codeoss.framework.view.component.IDataType;
import com.codeoss.framework.view.component.IVarName;
import com.codeoss.framework.view.component.Message;
import com.codeoss.framework.view.component.Page;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.view.model.SelectItem;
import com.codeoss.framework.view.pagebean.base.BasePageBean;
import com.codeoss.framework.view.pagebean.crud.PageBeanCRUDUtil;
import com.codeoss.framework.view.service.ITableComponentService;
import com.codeoss.framework.view.service.IVariableService;
import com.codeoss.framework.view.util.ComponentDataUtil;
import com.codeoss.framework.view.util.PageBeanUtil;

@Service
public class ListViewPageBean extends BasePageBean {
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private IVariableService variableService;
	@Autowired
	private ITableComponentService tableComponentService;
	@Autowired
	private ExportManager exportManager;
	@Autowired
	private IConverterStore converterStore;
	public static final String KEY_SEARCH_FIELD_LIST = "key_search_field_list";

	public static final String KEY_TABLE = "key_table";

	public static final String KEY_TABLE_FIELD_LIST = "key_table_field_list";

	@Value("${framework.base-path}")
	private String basePath;
	@Autowired
	private PageBeanUtil pageBeanUtil;
	@Autowired
	private ComponentDataUtil componentDataUtil;
	@Autowired
	private PageBeanCRUDUtil pageBeanCRUDUtil;
	@Autowired
	private Utils utils;
	public void beforeInit() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		if (page.isInit()) {
			return;
		}
		
		List<IDataBinding> searchDataBindingList =new ArrayList<IDataBinding>();
		pageBeanUtil.getFormFieldList(page, searchDataBindingList);
		page.setAttribute(KEY_SEARCH_FIELD_LIST, searchDataBindingList);

		pageBeanUtil.getComponent(yunContext,page,"table");
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) yunContext
				.getAttribute("__component__");
		page.setAttribute(KEY_TABLE, tableComponent);

		List<IDataBinding> tableFieldList = new ArrayList<IDataBinding>();
		pageBeanUtil.getDataBindingList(tableComponent, tableFieldList);
		page.setAttribute(KEY_TABLE_FIELD_LIST, tableFieldList);

		List<String> queryColumnList = new ArrayList<String>();
		page.setAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn", queryColumnList);
		for (int i = 0; i < tableFieldList.size(); i++) {
			queryColumnList.add(tableFieldList.get(i).getDataField());
		}
		page.setInit(true);
	}

	public void init() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		List<IDataBinding> searchDataBindingList=page.getAttribute(KEY_SEARCH_FIELD_LIST);
		for(int i=0;i<searchDataBindingList.size();i++) {
			variableService.setVariableValue(yunContext, ((IVarName)searchDataBindingList.get(i)).getVarName(), null);
		}
		DataSourceConfig dataSourceConfig = page.getDataSourceConfigList().get(0);
		pageBeanUtil.generateFormInfo(searchDataBindingList);
		yunContext.setMasterModel(dataSourceConfig.getTableName());

		List<String> queryColumnList=page.getAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn");
		Query query = new Query();
		
		String action = yunContext.getQueryMap().get("action");
		if("link".equals(action)) {
			String column=yunContext.getQueryMap().get("column");
			Long value=Long.parseLong(yunContext.getQueryMap().get("value"));
			query.add(Restrictions.eq(column, value));
		}
		
		query.setSelectColumnList(queryColumnList);
		com.codeoss.framework.view.component.Table tableComponent=(com.codeoss.framework.view.component.Table)page.getAttribute(KEY_TABLE);
		if (tableComponent.isPageable()) {
			query.setLimit(tableComponent.getPageSize());
		}
		query.setPage(1);
		
		List<IDataBinding> tableFieldList=page.getAttribute(KEY_TABLE_FIELD_LIST);
		componentDataUtil.getTableComponentData(yunContext, page, tableComponent, tableFieldList, query);
	}

	public void dataSearch() {
		dataSearch(true);
	}
	
	public void dataSearch(boolean pagination) {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		Query query = new Query();

		List<String> queryColumnList = page.getAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn");
		query.setSelectColumnList(queryColumnList);

		List<IDataBinding> searchDataBindingList = page.getAttribute(KEY_SEARCH_FIELD_LIST);
		for (int j = 0; j < searchDataBindingList.size(); j++) {
			IDataBinding dataBinding = searchDataBindingList.get(j);
			Object value = variableService.getVariableValue(yunContext, ((IVarName) dataBinding).getVarName());
			if (value != null) {
				if (((IDataType) dataBinding).getDataType().equals(DataTypeConstants.DATA_TYPE_STRING)) {
					String sValue=(String)value;
					if (!StringUtils.isEmpty(sValue)) {
						String lastChar=sValue.substring(sValue.length()-1,sValue.length());
						if(lastChar.equals("%")) {
							sValue=sValue.substring(0,sValue.length()-1);
							query.add(Restrictions.like(dataBinding.getDataField(), sValue));
						}else {
							query.add(Restrictions.eq(dataBinding.getDataField(), value));	
						}
					}
				} else {
					query.add(Restrictions.eq(dataBinding.getDataField(), value));
				}
			}
		}
		dataSearch(pagination,query);
	}

	public void dataSearch(boolean pagination,Query query) {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) page
				.getAttribute(KEY_TABLE);
		if(pagination) {
			query.setLimit(tableComponent.getPageSize());
		}
		String nextPage = yunContext.getViewRequest().getData().get(tableComponent.getId() + "_page");
		if (!StringUtils.isEmpty(nextPage)) {
			query.setPage(Integer.parseInt(nextPage));
		}	
		List<String> queryColumnList=page.getAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn");
		query.setSelectColumnList(queryColumnList);
		List<IDataBinding> tableFieldList=page.getAttribute(KEY_TABLE_FIELD_LIST);
		componentDataUtil.getTableComponentData(yunContext, page, tableComponent, tableFieldList, query);
	}
	
	@Transactional
	public void dataDelete() {
		YunContext yunContext = YunContext.getCurrentContext();
		String sIdValue =yunContext.getViewRequest().getData().get("id");
		Page page = yunContext.getPage();
		DataSourceConfig dataSourceConfig = page.getDataSourceConfigList().get(0);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		Table table=tableStore.get(dataSourceConfig.getTableName());
		Column keyColumn=table.getPrimaryKeyColumn();
		IConverter converter=converterStore.getConverter(keyColumn.getDataType());
		dataMap.put(keyColumn.getColumnName(), converter.convertStringToObject(sIdValue));
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) page
				.getAttribute(KEY_TABLE);
		pageBeanCRUDUtil.deleteTableData(yunContext, page, tableComponent, dataMap);
		dataSearch();
		yunContext.addMessage(new Message("删除成功"));
	}

	public void dataNew(String pageCode) {
		YunContext yunContext = YunContext.getCurrentContext();
		NavigatePageClientScript navigatePageClientScript = new NavigatePageClientScript();
		navigatePageClientScript.setPageId(yunContext.getPage().getId());
		navigatePageClientScript.setPageCode(pageCode);
		navigatePageClientScript.addPara("action", "dataNew");
		yunContext.addClientScript(navigatePageClientScript);
		yunContext.setRenderCompleted(true);
	}

	public void dataEdit(String pageCode) {
		YunContext yunContext = YunContext.getCurrentContext();
	    String sIdValue = yunContext.getViewRequest().getData().get("id");
		NavigatePageClientScript navigatePageClientScript = new NavigatePageClientScript();
		navigatePageClientScript.setPageId(yunContext.getPage().getId());
		navigatePageClientScript.setPageCode(pageCode);
		navigatePageClientScript.addPara("action", "dataEdit");
		navigatePageClientScript.addPara("id", sIdValue);
		yunContext.addClientScript(navigatePageClientScript);
		yunContext.setRenderCompleted(true);
	}

	public void dataPage() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) page.getAttribute(KEY_TABLE);
		String nextPage = yunContext.getViewRequest().getData().get(tableComponent.getId() + "_page");
		dataSort(Integer.parseInt(nextPage));
	}

	public List<Long> getSelectedKeyValueList() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) page
				.getAttribute(KEY_TABLE);
		return tableComponentService.getSelectedKeyValueList(yunContext, tableComponent);
	}
	
	public void dataExport() {
		dataSearch(false);
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) page.getAttribute(KEY_TABLE);
		TableData tableData =(TableData)yunContext.getAttribute(tableComponent.getId() + "_tabledata");
		Map<String, List<SelectItem>> selectItemMap =yunContext.getAttribute(tableComponent.getId() + "_selectItemMap");
		String filename=UUID.randomUUID().toString()+".xlsx";
		File newFile=new File(basePath+"/tempfile"+File.separator+filename);
		FileOutputStream fos=null;
		try {
			fos = new FileOutputStream(newFile);
			exportManager.exportExcel(yunContext,tableComponent, tableData, selectItemMap, fos);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}finally {
		    IOUtil.closeOutputStream(fos);	
		}
		JsWindow jsWindow=JsWindow.open("file/download?filename="+filename+"&displayName="+page.getName()+".xlsx"+"&X-Token="+yunContext.getToken());
		yunContext.addClientScript(jsWindow);
		yunContext.setRenderCompleted(true);
	}
	
	public void dataSort() {
		dataSort(1);
	}
	
	public void dataSort(int pageIndex) {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		Query query = new Query();

		List<String> queryColumnList = page.getAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn");
		query.setSelectColumnList(queryColumnList);

		List<IDataBinding> searchDataBindingList = page.getAttribute(KEY_SEARCH_FIELD_LIST);
		for (int j = 0; j < searchDataBindingList.size(); j++) {
			IDataBinding dataBinding = searchDataBindingList.get(j);
			Object value = variableService.getVariableValue(yunContext, ((IVarName) dataBinding).getVarName());
			if (value != null) {
				if (((IDataType) dataBinding).getDataType().equals(DataTypeConstants.DATA_TYPE_STRING)) {
					String sValue=(String)value;
					if (!StringUtils.isEmpty(sValue)) {
						String lastChar=sValue.substring(sValue.length()-1,sValue.length());
						if(lastChar.equals("%")) {
							sValue=sValue.substring(0,sValue.length()-1);
							query.add(Restrictions.like(dataBinding.getDataField(), sValue));
						}else {
							query.add(Restrictions.eq(dataBinding.getDataField(), value));	
						}
					}
				} else {
					query.add(Restrictions.eq(dataBinding.getDataField(), value));
				}
			}
		}
		query.setPage(pageIndex);
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) page.getAttribute(KEY_TABLE);
		if(tableComponent.isPageable()) {
			query.setLimit(tableComponent.getPageSize());
		}
		String sortField=yunContext.getViewRequest().getData().get(tableComponent.getId()+"_sortfield");
		String sortType=yunContext.getViewRequest().getData().get(tableComponent.getId()+"_sorttype");
		if(!StringUtils.isEmpty(sortField) && !"null".equals(sortField)) {
			page.findComponentById(yunContext, sortField);
			Component findComponent=yunContext.getFindComponent();
			if(findComponent instanceof IDataBinding) {
				utils.setHasOrderByClause(yunContext);
				String columnName=((IDataBinding)findComponent).getDataField();
				if("ascending".equals(sortType)) {
					query.addOrder(Order.asc(columnName));
				}else if("descending".equals(sortType)) {
					query.addOrder(Order.desc(columnName));
				}
			}
		}
		dataSearch(true,query);
	}
}
